home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 282_01 / walclock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-01-11  |  17.5 KB  |  870 lines

  1. /*
  2. TITLE:        Wall Clock;
  3. DATE:        9/19/88;
  4. DESCRIPTION:    "Analog clock face.";
  5. VERSION:    1.10;
  6. KEYWORDS:    Clock, Graphics, HGA, Hercules;
  7. FILENAME:    WALCLOCK.C
  8. WARNINGS:    "Requires Hercules monochrome graphics.";
  9. SEE-ALSO:    WALCLOCK.DAT, WALCLOCK.EXE;
  10. SYSTEM:        MS-DOS;
  11. COMPILERS:    Aztec;
  12. AUTHORS:    Dan Schechter;
  13.  */
  14. #include <stdio.h>
  15. #include <time.h>
  16. #include <math.h>
  17.  
  18. #define TICKTOCK    /* Delete this if you don't want the tick-tock. */
  19. #define NOMATH        /* Delete this if the program will always be
  20.             run on a computer with a floating-point coprocessor
  21.             and your compiler has FPU support. With NOMATH
  22.             defined, the program uses a table look-up to 
  23.             position the hands. This makes the program about twice
  24.             as large. If NOMATH is not defined, the program
  25.             calculates the positions of hands on the fly, but
  26.             an FPU is necessary if this is to be done fast enough
  27.             to keep up with real time. */
  28. #ifdef TICKTOCK
  29. #include <signal.h>
  30. #endif
  31.  
  32. #ifdef NOMATH
  33. #define VERSION "Version 1.10-t 9/19/88" 
  34. #else
  35. #define VERSION "Version 1.10-fpu 9/19/88" 
  36. #endif
  37.  
  38. #define CENTERH 360
  39. #define CENTERV 174
  40. #define TOPH 360
  41. #define TOPV 25
  42. #define LONG 125
  43. #define SHORT 75
  44.  
  45. #define INDEXPORT 0x3B4
  46. #define CONTROLPORT 0x3b8
  47. #define DATAPORT 0x3b5
  48. #define CONFIGPORT 0x3bf
  49. #define SCREEN0 0xb0000     /* Absolute address for page 0. */
  50. #define SCREEN1 0xb8000     /* Absolute address for page 1. */
  51. #define ROMFONT 0xffa6e       /* Absolute address of IBM ROM character set. */
  52.  
  53. void drawclock(void), controller(void), line(int,int,int,int,int), 
  54.      gocircle(int,int), _drawclock(void), 
  55.      hand(int,int,int,int,int), writetd(int,int,int,int, struct tm *), 
  56.      markers(void), g_write(char *,int,int), sigexit(int), cleardot(int,int), 
  57.      reagantime(struct tm *), chinatime(void), menu(void), 
  58.      stepclock(void), writedot(int,int), g_putch(int,int,int), sw_scr(int), 
  59.      g_mode(void), t_mode(void), *abstoptr(unsigned long),
  60.      tick(void), soundon(void), soundoff(void), tick_init(void);
  61.  
  62. int  sqroot(long);
  63.  
  64. char *day[7] = {
  65.     "Sunday   ",
  66.     "Monday   ",
  67.     "Tuesday  ",
  68.     "Wednesday",
  69.     "Thursday ",
  70.     "Friday   ",
  71.     "Saturday "
  72. };
  73. char *month[12] = {
  74.     "January ",
  75.     "February ",
  76.     "March ",
  77.     "April ",
  78.     "May ",
  79.     "June ",
  80.     "July ",
  81.     "August ",
  82.     "September ",
  83.     "October ",
  84.     "November ",
  85.     "December "
  86. };
  87.  
  88. int gdata[12] = { 
  89.     0x35, 0x2d, 0x2e, 0x7, 0x5b, 0x2, 0x57, 0x57, 0x2, 0x3, 0x0, 0x0 
  90. };
  91. int tdata[12] = { 
  92.     0x61, 0x50, 0x52, 0xf, 0x19, 0x6, 0x19, 0x19, 0x2, 0xd, 0xb, 0xc 
  93. };
  94.  
  95. int h24[24] = { 53, 61, 68, 73, 76, 77, 76, 73, 69, 60, 52, 44,
  96.         36, 28, 21, 16, 13, 12, 13, 16, 21, 28, 36, 44 };
  97. int v24[24] = { 5, 20, 48, 86, 128, 171, 215, 256, 296, 318, 333, 340,
  98.         333, 321, 293, 257, 214, 170, 127, 82, 45, 20, 5, 0 };
  99. int h12[12] = { 61, 73, 77, 73, 61, 45, 29, 17, 13, 16, 28, 44 };
  100. int v12[12] = { 20, 86, 171, 256, 318, 340, 318, 257, 170, 82, 20, 0 };
  101.  
  102. char *numbers12[12] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", 
  103.             "11", "12" };
  104. char *numbers24[24] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", 
  105.             "11", "12", "13", "14", "15", "16", "17", "18", 
  106.             "19", "20", "21", "22", "23", "24" };
  107. char *numbers12_a[12] = { "11", "10", "9", "8", "7", "6", "5", "4", "3", 
  108.             "2", "1", "12" };
  109. char *numbers24_a[24] = { "23", "22", "21", "20", "19", "18", "17", "16", 
  110.             "15", "14", "13", "12", "11", "10", "9", "8", "7", 
  111.             "6", "5", "4", "3", "2", "1", "24" };
  112.  
  113. thymelimit[7] = { 60, 60, 24, 0, 12, 99, 7 };
  114. monthlimit[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  115.  
  116. unsigned char *screen, *screen0, *screen1, *font ; 
  117. int *thyme[7];
  118. char twentyfour=0,location='l';
  119.  
  120. int main()
  121. {
  122.     
  123.     screen0=abstoptr(SCREEN0);
  124.     screen=screen1=abstoptr(SCREEN1);
  125.     font=abstoptr(ROMFONT);
  126.     system("break off");
  127.     g_mode();
  128. #ifdef TICKTOCK
  129.     signal (SIGINT, (void (*)(int)) sigexit);
  130.     tick_init();
  131. #endif
  132.     drawclock();
  133.     controller();
  134.     t_mode();
  135.     scr_clear();
  136.     exit(0);
  137. }
  138.  
  139. void drawclock()
  140. {
  141.     
  142.     int x,y,off,cx=CENTERH,cy=CENTERV,ex=TOPH,ey=TOPV;
  143.     long r,xr,yr,xx,yy;
  144.     
  145.     sw_scr(-1);
  146.     xr=cx-ex;
  147.     yr=cy-ey;
  148.     r=sqroot((xr*xr)+(yr*yr))+1;
  149.     off=(r*100)/141;
  150.     
  151.     gocircle(cy+(int)r-1,cx);
  152.     gocircle(cy-(int)r+1,cx);
  153.     
  154.     for(x=1;x<=off;x++){
  155.         xx=x;
  156.         xx*=xx;
  157.         y=sqroot(r*r-xx);
  158.         gocircle(cy+y,cx+x);
  159.         gocircle(cy+y,cx-x);
  160.         gocircle(cy-y,cx+x);
  161.         gocircle(cy-y,cx-x);
  162.      }
  163.     
  164.     gocircle(cy,cx+(int)r-1);
  165.     gocircle(cy,cx-(int)r+1);
  166.     
  167.     for(y=1;y<=off;y++){
  168.         yy=y;
  169.         yy*=yy;
  170.         x=sqroot(r*r-yy);
  171.         gocircle(cy+y,cx+x);
  172.         gocircle(cy+y,cx-x);
  173.         gocircle(cy-y,cx+x);
  174.         gocircle(cy-y,cx-x);
  175.     }
  176.     markers();
  177.     g_write("WALLCLOCK - KITTENSOFT",340,0);
  178.     g_write(VERSION,340,64);
  179.     
  180.     if (twentyfour)
  181.         for (x=0;x<24;x++) {
  182.             if (location=='a') 
  183.                 g_write(numbers24_a[x],v24[x],h24[x]);
  184.             else 
  185.                 g_write(numbers24[x],v24[x],h24[x]);
  186.         }
  187.     else
  188.         for (x=0;x<12;x++){
  189.             if (location=='a')
  190.                 g_write(numbers12_a[x],v12[x],h12[x]);
  191.             else 
  192.                 g_write(numbers12[x],v12[x],h12[x]);
  193.         }
  194.     menu();
  195.     memcpy(screen1,screen0,32767);
  196. }
  197.  
  198. void controller()
  199. {
  200.     int s,m,h,dh,dm,os,odm,odh,oos,oodm,oodh,q,h24;
  201.     struct tm t;
  202.     char meridian;
  203.     
  204.     thyme[0]=&(t.tm_sec);
  205.     thyme[1]=&(t.tm_min);
  206.     thyme[2]=&(t.tm_hour);
  207.     thyme[3]=&(t.tm_mday);
  208.     thyme[4]=&(t.tm_mon);
  209.     thyme[5]=&(t.tm_year);
  210.     thyme[6]=&(t.tm_wday);
  211.  
  212.     os=odm=odh=s=dm=dh=1;
  213.     for(;;){
  214.         switch (inkey()){
  215.             case 'X':
  216.             case 'q':
  217.             case 'Q':
  218.             case 'x': 
  219.             case 3:
  220.                 return;
  221.             case 'a': 
  222.             case 'A':
  223.                 location='a';
  224.                 os=odm=odh=s=dm=dh=1;
  225.                 drawclock();
  226.                 break;
  227.             case 'l':
  228.             case 'L':
  229.                 location='l';
  230.                 os=odm=odh=s=dm=dh=1;
  231.                 drawclock();
  232.                 break;
  233.             case 'c':
  234.             case 'C':
  235.                 dostime(&t);
  236.                 location='c';
  237.                 os=odm=odh=s=dm=dh=1;
  238.                 drawclock();
  239.                 break;
  240.             case 'r':
  241.             case 'R':
  242.                 location='r';
  243.                 os=odm=odh=s=dm=dh=1;
  244.                 drawclock();
  245.                 break;
  246.             case '\t':
  247.                 twentyfour ^=1;
  248.                 os=odm=odh=s=dm=dh=1;
  249.                 drawclock();
  250.                 break;
  251.             case 0: break;
  252.         }
  253.         oos=os;
  254.         oodm=odm;
  255.         oodh=odh;
  256.         os=s;
  257.         odm=dm;
  258.         odh=dh;
  259.         switch (location) {
  260.             case 'c': 
  261.                 chinatime(); 
  262.                 break;
  263.             case 'r': 
  264.                 reagantime(&t); 
  265.                 break;
  266.             case 'a':
  267.             case 'l':
  268.                 do dostime(&t);
  269.                 while (os==t.tm_sec); 
  270.                 break;
  271.         }
  272.         sw_scr(0);
  273. #ifdef TICKTOCK
  274.         tick();
  275. #endif
  276.         s=t.tm_sec;
  277.         m=t.tm_min;
  278.         h=t.tm_hour;
  279.         dh=h;
  280.         if (twentyfour==0){        
  281.             if (dh>11) dh-=12;
  282.             if (h>11) meridian='P';
  283.             else meridian='A';
  284.             if (h>12) h-=12;
  285.             if (h==0) h=12;
  286.         }
  287.         dh= dh*60+m;
  288.         dm= m*6+s/10;
  289.         
  290.         hand(oos,60,LONG,0,'e');
  291.         if (oodm!=dm) hand(oodm,360,LONG,1,'e');
  292.         if (oodh!=dh) {
  293.             if (twentyfour) hand(oodh,1440,SHORT,1,'e');
  294.             else hand(oodh,720,SHORT,1,'e');
  295.         }
  296.         hand(s,60,LONG,0,'d');
  297.         hand(dm,360,LONG,1,'d');
  298.         if (twentyfour) hand(dh,1440,SHORT,1,'d');
  299.         else hand(dh,720,SHORT,1,'d');
  300.         writetd(s,m,h,meridian,&t);
  301.     }
  302. }
  303.  
  304. /* The following toggles the active screen (the one being displayed)
  305. and also toggles the screen pointer (the one being written to) so that
  306. the program is always displaying the screen not being written to. */
  307.  
  308. void sw_scr(q)
  309. int q;
  310. {
  311.     static int scr;
  312.     
  313.     if (q==-1){
  314.         screen=screen1;
  315.         scr = 0;
  316.         memset(screen0,0,32767);
  317.         memset(screen1,0,32767);
  318.         outportb(CONTROLPORT, 10 | scr);
  319.         g_write("Please stand by...",100,30);
  320.     }
  321.     scr ^= 128;
  322.     outportb(CONTROLPORT, 10 | scr);
  323.     if (screen==screen0) screen=screen1;
  324.     else screen=screen0;
  325. }
  326.  
  327. #ifdef NOMATH
  328. #include "clock.dat"
  329.  
  330. void hand(n,num,length,w,q)
  331. int n,num,length,w,q;
  332. {
  333.     int v,h;
  334.     
  335.     switch (num) {
  336.         case 60: n*=6; break;
  337.         case 720: n*=2; break;
  338.     }
  339.     switch (length) {
  340.         case LONG: 
  341.             h=hlong[n];
  342.             v=vlong[n];
  343.             break;
  344.         case SHORT:
  345.             h=hshort[n];
  346.             v=vshort[n];
  347.             break;
  348.     }
  349.  
  350.     if (location=='a') h=((h-CENTERH)*(-1))+CENTERH; /* Austrailia */
  351.     
  352.     line(h,v,CENTERH,CENTERV,q);
  353.  
  354.     if (w) {
  355.         line(h+1,v,CENTERH+1,CENTERV,q);
  356.         line(h,v+1,CENTERH,CENTERV+1,q);
  357.  
  358. /* The following 3 lines give the hands better bredth. But they are
  359. very time consuming. Delete them if the Norton Utilities Sysinfo
  360. program rates your computer at 2.5 or less, relative to an IBM-PC. 
  361.  
  362.         line(h+1,v+1,CENTERH+1,CENTERV+1,q);
  363.         line(h-1,v,CENTERH-1,CENTERV,q);
  364.         line(h-1,v+1,CENTERH-1,CENTERV+1,q); */
  365.     }
  366. }
  367.  
  368. #else
  369.  
  370. void hand(n,num,length,w,q)
  371. int n,num,length,w,q;
  372. {
  373.     double angle,x,y,sin(),cos(),sweep;
  374.     int v,h;
  375.     
  376.     sweep=(double)n/(double)num;
  377.     angle= sweep *2.0*3.1415926536;  /* in radians */
  378.     x= sin(angle)*(double)length;
  379.     y= cos(angle)*(double)length;
  380.     
  381.     x*=1.5;
  382.     h=(int)x+CENTERH;
  383.     v=CENTERV-(int)y;
  384.  
  385.     if (location=='a') h=((h-CENTERH)*(-1))+CENTERH; /* Austrailia */
  386.     
  387.     line(h,v,CENTERH,CENTERV,q);
  388.     if (w) {
  389.         line(h+1,v,CENTERH+1,CENTERV,q);
  390.         line(h,v+1,CENTERH,CENTERV+1,q);
  391.  
  392. /* The following 3 lines give the hands better bredth. But they are
  393. very time consuming. Delete them if the Norton Utilities Sysinfo
  394. program rates your computer at 2.0 or less, relative to an IBM-PC. 
  395.  
  396.         line(h+1,v+1,CENTERH+1,CENTERV+1,q);
  397.         line(h-1,v,CENTERH-1,CENTERV,q);
  398.         line(h-1,v+1,CENTERH-1,CENTERV+1,q); */
  399.     }
  400. }
  401.  
  402. #endif
  403.  
  404. void markers()
  405. {
  406.     double angle,x,y,x2,y2,sin(),cos(),sweep;
  407.     int v,h,v2,h2,i;
  408.     
  409.     if (twentyfour) sweep=0.2617994;
  410.     else sweep=0.5235988;
  411.     for (angle=0.0;angle<6.2;angle+=sweep){
  412.         x=sin(angle) * (LONG+7) * 1.5;
  413.         y=cos(angle) * (LONG+7);
  414.         x2=sin(angle) * (LONG+17) * 1.5;
  415.         y2=cos(angle) * (LONG+17);
  416.         h=(int)x+CENTERH;
  417.         h2=(int)x2+CENTERH;
  418.         v=CENTERV-(int)y;
  419.         v2=CENTERV-(int)y2;
  420.     
  421.         line(h,v,h2,v2,'d');
  422.     }
  423.     for (angle=0.0,i=0;angle<6.18;angle+=0.10472){
  424.         if ((i++)%5==0) continue;
  425.         x=sin(angle) * (LONG+10) * 1.5;
  426.         y=cos(angle) * (LONG+10);
  427.         h=(int)x+CENTERH;
  428.         v=CENTERV-(int)y;
  429.     
  430.         writedot(h,v);
  431.     }
  432. }
  433.  
  434. void line(h1,v1,h2,v2,m)
  435. int h1,v1,m;
  436. {
  437.     long int i,x,y,x1,y1,x2,y2,xd,yd,xstepdir,ystepdir,stepsize;
  438.     int h,v;
  439.     
  440.     x1=h1;
  441.     x2=h2;
  442.     y1=v1;
  443.     y2=v2;
  444.     xd=x2-x1;
  445.     yd=y2-y1;
  446.     if ((!(xd))&&(!(yd))) return;
  447.  
  448.     if (xd>0l) xstepdir=1l;
  449.     else xstepdir=-1l;
  450.     if (yd>0l) ystepdir=1l;
  451.     else ystepdir=-1l;
  452.  
  453.     if ((xd*xd)>(yd*yd)){
  454.         stepsize=(yd<<16)/xd;
  455.         if (stepsize<0) stepsize*=-1;
  456.         for(i=0,x=x1;x!=x2;i++,x+=xstepdir){
  457.             y=y1+ystepdir*((stepsize*i)>>16);
  458.             h=x;
  459.             v=y;
  460.             if (m=='d') writedot(h,v);
  461.             else cleardot(h,v);
  462.         }
  463.     }
  464.     else {
  465.         stepsize=(xd<<16)/yd;
  466.         if (stepsize<0) stepsize*=-1;
  467.         for(i=0,y=y1;y!=y2;i++,y+=ystepdir){
  468.             x=x1+xstepdir*((stepsize*i)>>16);
  469.             h=x;
  470.             v=y;
  471.             if (m=='d') writedot(h,v);
  472.             else cleardot(h,v);
  473.         }
  474.     }
  475.     if (m=='d') writedot(CENTERH,CENTERV);
  476.     else cleardot(CENTERH,CENTERV);
  477. }
  478.  
  479. /* The following must cause a one-second pause. Check your compiler
  480. documentation for the function clock(), and re-write this if necessary. */
  481.  
  482. void g_sleep()
  483. {
  484.     long a,clock();
  485.  
  486.     a=clock();
  487.     while ( clock()-a < 100)
  488.         ;
  489. }
  490.  
  491. void g_mode()
  492. {
  493.     int i;
  494.     
  495.     outportb(CONFIGPORT,3);
  496.     outportb(CONTROLPORT,0);
  497.     for(i=0;i<12;i++){
  498.         outportb(INDEXPORT,i);
  499.         outportb(DATAPORT,gdata[i]);
  500.     }
  501.     outportb(CONTROLPORT,2);
  502.     g_sleep();
  503.     memset(screen0,0,65535);
  504.     outportb(CONTROLPORT,10);
  505. }
  506. void t_mode()
  507. {
  508.     int i;
  509.     
  510.     outportb(CONTROLPORT,0);
  511.     for(i=0;i<12;i++){
  512.         outportb(INDEXPORT,i);
  513.         outportb(DATAPORT,tdata[i]);
  514.     }
  515.     g_sleep();
  516.     outportb(CONTROLPORT,40);
  517. }
  518.  
  519. /* The following are the "easy to read" write and clear dot functions. 
  520. They are not used, however, in the interest of speed. The versions actually
  521. used are logically the same but avoid the use of temporary variables.
  522.  
  523. void writedot(x,y)
  524. int x,y;
  525. {
  526.     unsigned off;
  527.     unsigned char c,bit;
  528.     
  529.     off=(unsigned)( 0x2000 * (y%4) + 90*(y/4) + x/8 );
  530.     c=screen[off];
  531.     bit = 1<< (7-x%8);
  532.     c |= bit;
  533.     screen[off]=c;
  534. }
  535. void cleardot(x,y)
  536. int x,y;
  537. {
  538.     unsigned off;
  539.     unsigned char c,bit;
  540.     
  541.     off=(unsigned)( 0x2000 * (y%4) + 90*(y/4) + x/8 );
  542.     c=screen[off];
  543.     bit = (~(1<< (7-x%8)));
  544.     c &= bit;
  545.     screen[off]=c;
  546. }
  547. void g_putch(c,h,v)
  548. int c,h,v;
  549. {
  550.     int i;
  551.     unsigned char scan_line;
  552.     unsigned off;
  553.     
  554.     for (i=0;i<8;i++,v++){
  555.         scan_line=font[c*8+i];
  556.         off=(unsigned)( 0x2000 * (v%4) + 90*(v/4) + h );
  557.         screen[off]= scan_line;
  558.     }
  559. }
  560.  */
  561.  
  562. void writedot(x,y)
  563. int x,y;
  564. {
  565.     
  566.     screen[0x2000*(y%4)+90*(y/4)+x/8] |= (1<<(7-x%8));
  567. }
  568. void cleardot(x,y)
  569. int x,y;
  570. {
  571.     
  572.     screen[0x2000*(y%4)+90*(y/4)+x/8] &= (~(1<<(7-x%8)));
  573. }
  574.  
  575. void g_putch(c,h,v)
  576. int c,h,v;
  577. {
  578.     int i;
  579.     
  580.     for (i=0;i<8;i++,v++)
  581.         screen[0x2000*(v%4)+90*(v/4)+h]= font[c*8+i];
  582. }
  583.  
  584. void g_write(s,v,h)
  585. char *s;
  586. int h,v;
  587. {
  588.     
  589.     while (*s) g_putch(*s++,h++,v);
  590. }
  591. void writetd(s,m,h,meridian,t)
  592. int s,m,h,meridian;
  593. struct tm *t;
  594. {
  595.     char buf[25],*wp;
  596.     int i=0;
  597.     
  598.     if (h>=10) buf[i++]=h/10+48;
  599.     buf[i++]= h%10+48;
  600.     buf[i++]= ':';
  601.     buf[i++]= m/10+48;
  602.     buf[i++]= m%10+48;
  603.     buf[i++]= ':';
  604.     buf[i++]= s/10+48;
  605.     buf[i++]= s%10+48;
  606.     buf[i++]= ' ';
  607.     if (twentyfour==0){
  608.         buf[i++]= ' ';
  609.         buf[i++]= meridian;
  610.         buf[i++]= 'M';
  611.         buf[i++]= ' ';
  612.     }
  613.     buf[i++]= 0;
  614.     g_write(buf,36,1);
  615.  
  616.     g_write(day[t->tm_wday],0,1);
  617.     strcpy(buf,month[t->tm_mon]);
  618.     wp=buf;
  619.     while (*wp!=' ') wp++;
  620.     wp++;
  621.     if (t->tm_mday>=10){
  622.         (*wp++)=t->tm_mday/10+48;
  623.         (*wp++)=t->tm_mday%10+48;
  624.     }
  625.     else (*wp++)=t->tm_mday+48;
  626.     *wp=0;
  627.     strcat(buf,"          ");
  628.     
  629.     g_write(buf,12,1);
  630.     g_putch('1',1,24);
  631.     g_putch('9',2,24);
  632.     g_putch(t->tm_year/10+48,3,24);
  633.     g_putch(t->tm_year%10+48,4,24);
  634. }
  635. void gocircle(y,x)
  636. int y,x;
  637. {
  638.     x-=CENTERH;
  639.     x+= (x/2);
  640.     x+=CENTERH;
  641.     
  642.     writedot(x,y);
  643. }
  644. int sqroot(n)
  645. long n;
  646. {
  647.     long r1,r2;
  648.     r1=n;
  649.     r2=1l;
  650.  
  651.     while (r1>r2){
  652.         r1=(r1+r2)/2;
  653.         r2=n/r1;
  654.     }
  655.     return((int)r1);
  656. }
  657.  
  658. /* The following increments the time by one second. It is used only
  659. by chinatime(), which begins with the real time but then moves
  660. forward at a somewhat random pace. */
  661.  
  662. void stepclock()
  663. {
  664.     int i;
  665.     
  666.     (*thyme[0])++;
  667.     for (i=0;i<6;i++){
  668.         if ( *thyme[i]==thymelimit[i] ) {
  669.             if (i==2){
  670.                 (*thyme[6])++;
  671.                 if (*thyme[6]==7) *thyme[6]=0;
  672.             }
  673.             if ((i==3) && (*thyme[i]!=monthlimit[*thyme[i]]))
  674.                 continue;
  675.             *thyme[i]=0;
  676.             if (i==3) *thyme[i]=1;
  677.             if (i==5) break;
  678.             (*thyme[i+1])++;
  679.         }
  680.     }
  681. }
  682.  
  683. /* The following function is intended to sleep a random length of
  684. time between 1/4 second and 1 1/4 seconds, more or less, to give an
  685. uneven movement of the clock and simulate an inaccurate water clock.
  686. This is intended as a joke. Water clocks are actually much more
  687. accurate than this. Depending on the action of clock(), which varies
  688. from one compiler to the next, you may have to revise this function. */
  689.  
  690. void chinatime()
  691. {
  692.     long a,clock();
  693.     int delay;
  694.  
  695.     delay= rando()%100;
  696.     if (delay<50) delay/=2;
  697.     if (delay>75) delay+=50; 
  698.     a=clock();  
  699.     while( clock()-a < delay )
  700.         ;
  701.     stepclock();
  702.  
  703. }
  704. void reagantime(t)
  705. struct tm *t;
  706. {
  707.     long a;clock();
  708.     
  709.     a=clock();
  710.     while ( clock()-a <200 ) ;
  711.     
  712.     t->tm_sec = rando()%60;
  713.     t->tm_min = rando()%60;
  714.     t->tm_hour = rando()%24;
  715.     t->tm_mday = rando()%40+1;
  716.     t->tm_mon = rando()%12;
  717.     t->tm_year = rando()%100;
  718.     t->tm_wday = rando()%7;
  719. }
  720.  
  721. /* A rudimentary but useable pseudo-random integer generator: */
  722.  
  723. int rando()
  724. {
  725.     static long zi;
  726.     static int seed=1;
  727.     
  728.     struct tm T;
  729.     if (seed) {
  730.         seed=0;
  731.         dostime(&T);
  732.         zi=(long)T.tm_hsec*(long)T.tm_sec+(long)T.tm_hour*(long)T.tm_min;
  733.     }
  734.     zi*=23;
  735.     zi+=17;
  736.     zi%=32749;
  737.     return((int)zi);
  738. }
  739.  
  740. char *menutext[4][8] = {
  741. {
  742. "        Local time.",
  743. "",
  744. "",
  745.        "Press your choice:",
  746.        "(A)ustralian time.",
  747.        "(C)hinese time.",
  748.        "(R)eagan time.",
  749.        "TAB: 24-hr format." },
  750.       
  751. {
  752. "Chinese time. In China",
  753. "the use of water clocks",
  754. "makes time less accurate.",
  755.        "Press your choice:",
  756.        "(A)ustralian time.",
  757.        "(L)ocal time.",
  758.        "(R)eagan time.",
  759.        "TAB: 24-hr format." },
  760.  
  761. {
  762. "  Australian time. Due to",
  763. "  the Coriolis force,",
  764. "  clocks run backwards.",
  765.        "Press your choice:",
  766.        "(L)ocal time.",
  767.        "(C)hinese time.",
  768.        "(R)eagan time.",
  769.        "TAB: 24-hr format." },
  770.  
  771. {
  772. "   The time according to",
  773. "   Ronald Reagan. He gets",
  774. "   confused sometimes.",
  775.        "Press your choice:",
  776.        "(A)ustralian time.",
  777.        "(C)hinese time.",
  778.        "(L)ocal time.",
  779.        "TAB: 24-hr format." }
  780. };
  781.  
  782. void menu()
  783. {
  784.     int i,m,j;
  785.     
  786.     switch(location){
  787.         case 'a': m=2; j=528; break;
  788.         case 'c': m=1; j=512; break;
  789.         case 'l': m=0; j=568; break;
  790.         case 'r': m=3; j=536; break;
  791.     }
  792.     
  793.     for (i=0;i<3;i++) g_write(menutext[m][i],i*10,65);
  794.     for (i=3;i<8;i++) g_write(menutext[m][i],(i)*10,72);  
  795.     if (twentyfour) g_write("12",70,77);
  796.     g_write("X - Exit.",80,81);
  797.     
  798.     line(j,0,j,30,'d');
  799.     line(j,30,568,30,'d');
  800.     line(568,30,568,80,'d');
  801.     line(568,80,640,80,'d');
  802.     line(640,80,640,90,'d');
  803.     line(640,90,719,90,'d');
  804. }
  805.  
  806. /* The following function may be compiler-dependent. Alas that
  807. C function libraries do not have a standardized inkey() function! */
  808.  
  809. int inkey()
  810. {
  811.     
  812.     return(bdos(0x600,0xff,0));
  813. }
  814.  
  815. /* If your compiler does not have abstoptr you can use this one: */
  816.  
  817. void *abstoptr(abs)
  818. unsigned long abs;
  819. {
  820.     unsigned long h,l;
  821.     
  822.     l=abs&15L;
  823.     h=abs>>4;
  824.     h<<=16;
  825.     return ( (void far *)(h|l) );
  826. }
  827.  
  828. #ifdef TICKTOCK
  829.  
  830. int on_sound,off_sound;
  831.  
  832. void sigexit(q)
  833. int q;
  834. {
  835.     t_mode();
  836.     scr_clear();
  837.     exit(0);
  838. }
  839.  
  840. void tick()
  841. {
  842.     long adj;
  843.     
  844.     soundon();
  845.     soundoff();
  846. }
  847. void soundon()
  848. {
  849.     int temp;
  850.     
  851.     outportb(0x43,0xb6);
  852.     outportb(0x42, 1000 & 0xff);
  853.     outportb(0x42, 1000 >> 8);
  854.     
  855.     outportb(0x61,on_sound);
  856. }
  857. void soundoff()
  858. {
  859.     int temp;
  860.     
  861.     outportb(0x61,off_sound);
  862. }
  863. void tick_init()
  864. {
  865.  
  866.     off_sound = inportb(0x61);
  867.     on_sound = off_sound | 3;
  868. }
  869. #endif
  870.